# SystemDetection.cmake — 系统检测与基础编译选项设置

# 防止本模块被重复包含，多次执行导致重复追加编译选项或重复设置变量。
if(DEFINED SYSTEM_DETECTION_INCLUDED)
    return()
endif()
set(SYSTEM_DETECTION_INCLUDED true)

# 引入 C/C++ 编译器特性检测模块，用于判断某些编译参数是否可用。
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)

# -------------------------------
# 统一追加基础诊断相关的编译/链接选项
# -------------------------------
# Rust 的编译信息友好度很高，下面根据不同编译器追加彩色输出、caret 指示、fix-it 建议等。
set(BASE_DIAGNOSTIC_FLAGS "")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    list(APPEND BASE_DIAGNOSTIC_FLAGS
        # "-fdiagnostics-color=always"        # 始终启用彩色诊断信息
        # "-fdiagnostics-show-caret"          # 在报错位置下方显示 ^ 指示符
        # "-fdiagnostics-column-origin"       # 显示列号，定位更精准
        # "-fdiagnostics-path-format=inline"  # 展开调用路径信息为内联格式（GCC 12+ 支持）
        "-fno-diagnostics-show-option"      # 隐藏具体的 -Wxxx 选项，避免信息噪音
        "-fmessage-length=0"                # 禁止 GCC 自动换行，方便终端和 IDE 阅读
    )
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    list(APPEND BASE_DIAGNOSTIC_FLAGS
        # "-fcolor-diagnostics"               # 启用彩色诊断（部分终端默认关闭时强制开启）
        # "-fansi-escape-codes"               # 即使终端兼容性不佳也尝试输出 ANSI 颜色
        "-fdiagnostics-show-note-include-stack" # 报错时显示 include 链，类似 Rust 的 note 信息
        "-fdiagnostics-absolute-paths"      # 使用绝对路径，配合 IDE 跳转更稳定
        "-fdiagnostics-parseable-fixits"    # 输出可解析的 fix-it 建议（clangd/IDE 可直接应用）
    )
endif()

# 将基础诊断选项拼接到 C/C++ 编译标志中。
foreach(flag IN LISTS BASE_DIAGNOSTIC_FLAGS)
    string(APPEND CMAKE_C_FLAGS " ${flag}")
    string(APPEND CMAKE_CXX_FLAGS " ${flag}")
endforeach()

# -------------------------------
# GCC 静态分析器支持（若可用）
# -------------------------------
# GCC 10+ 提供 -fanalyzer，可在编译阶段做额外静态分析，捕捉潜在运行时问题。
option(ENABLE_GNU_ANALYZER "Enable GCC static analyzer (-fanalyzer)" OFF)
if(ENABLE_GNU_ANALYZER AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    include(CheckCXXCompilerFlag)
    check_cxx_compiler_flag("-fanalyzer" HAS_GNU_ANALYZER)
    if(HAS_GNU_ANALYZER)
        add_compile_options(
            $<$<COMPILE_LANG_AND_ID:C,GNU>:-fanalyzer>
            $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-fanalyzer>
        )
    endif()
endif()

# -------------------------------
# clangd / clang-tidy 辅助
# -------------------------------
# 若生成 compile_commands.json，可被 clangd / clang-tidy 使用，获取实时诊断和自动修复建议。
if(CMAKE_EXPORT_COMPILE_COMMANDS)
    message(STATUS "compile_commands.json 将用于 clangd/clang-tidy，可获得 fix-it 建议")
endif()

# -------------------------------
# 根据构建类型设置基础优化 / 调试参数
# -------------------------------
# 保留原有逻辑：Debug/Release/Other 分别设置 -g、优化等级、-D 宏以及链接器 build-id。
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    string(APPEND CMAKE_C_FLAGS " -g -O0 -Wall -fPIC -D_DEBUG")
    string(APPEND CMAKE_CXX_FLAGS " -g -O0 -Wall -fPIC -D_DEBUG")
    string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--build-id=sha1")
    string(APPEND CMAKE_EXE_LINKER_FLAGS " -rdynamic")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
    string(APPEND CMAKE_C_FLAGS " -g -O2 -Wall,-fPIC -D_NDEBUG")
    string(APPEND CMAKE_CXX_FLAGS " -g -O2 -Wall -fPIC -D_NDEBUG")
    string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--build-id=sha1")
    string(APPEND CMAKE_EXE_LINKER_FLAGS " -rdynamic")
else()
    string(APPEND CMAKE_C_FLAGS " -g -O0 -Wall -fPIC -D_DEBUG")
    string(APPEND CMAKE_CXX_FLAGS " -g -O0 -Wall -fPIC -D_DEBUG")
    string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--build-id=sha1")
    string(APPEND CMAKE_EXE_LINKER_FLAGS " -rdynamic")
endif()

# 打印当前主机与目标系统的处理器信息，便于调试脚本行为。
message(STATUS "CMAKE_HOST_SYSTEM_PROCESSOR=${CMAKE_HOST_SYSTEM_PROCESSOR}")
message(STATUS "CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}")

# -------------------------------
# 根据用户配置决定编译 32 位或 64 位
# -------------------------------
# 默认采用 64 位；特殊平台（ARM/AIX）在后面逻辑中会覆盖此标志。
if(USE_32BITS STREQUAL "True")
    message(STATUS "Using 32bits")
    set(BIT_FLAG "-m32")
else()
    message(STATUS "Using 64bits")
    set(BIT_FLAG "-m64") # arm 没有 -m64，AIX 需使用 -maix64
endif()

# -------------------------------
# 根据目标系统设置特定的编译选项和输出路径
# -------------------------------
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)$")
        message(STATUS "Configuring on/for ARM64 Linux")
        # 为 pthread 配置显式变量，确保 find_package(Threads) 的结果符合预期。
        set(CMAKE_THREAD_LIBS_INIT "-lpthread")
        set(CMAKE_HAVE_THREADS_LIBRARY 1)
        set(CMAKE_USE_WIN32_THREADS_INIT 0)
        set(CMAKE_USE_PTHREADS_INIT 1)

        # ARM64 不再支持 32 位编译，若用户强制指定则直接报错。
        if(USE_32BITS STREQUAL "True")
            message(FATAL_ERROR "No longer support 32-bit builds on ARM64 architecture")
            return()
        endif()

        # ARM64 默认使用本地位宽（无需 -m64），并设置动态库输出目录。
        set(BIT_FLAG "")
        set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../dist/arm64)
    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
        message(STATUS "Configuring on/for x86_64 Linux")
        set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../dist/lnx64)
    else()
        message(STATUS "Configuring on/for unknown architecture Linux")
    endif()

    # 将位数标志附加到最终的 C/C++ 编译标志中。
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${BIT_FLAG}")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BIT_FLAG}")

elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX")
    message(STATUS "Configuring on/for IBM AIX")
    # IBM AIX 不再支持 32 位构建，这里直接阻止继续执行。
    if(USE_32BITS STREQUAL "True")
        message(FATAL_ERROR "No longer support 32-bit builds on IBM AIX architecture")
        return()
    endif()
    # AIX 需要使用 -maix64 指定 64 位 ABI。
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maix64")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maix64")
    set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../dist/aix64)

else()
    # 未覆盖的平台直接报错，避免产生未知编译行为。
    message(FATAL_ERROR "Configuring on/for unknown ${CMAKE_SYSTEM_NAME}")
    return()
endif()